
#include <stdlib.h>
#include "alloc.h"
#define LOG_TAG "Alloc"
#include "log.h"

// 空闲块列表
static Block *FreeBlocks = NULL;
static HeapEty FileHeep = {&FileHeep.head};
Heap MainHeap = &FileHeep;

// 初始化内存堆
void InitHeap(Heap hp)
{
    hp->head.next = NULL;
    hp->head.begin = hp->head.end = hp->head.avail = NULL;
    hp->last = &hp->head;
}

// 申请指定大小内存，功能类似于malloc
void *HeapAllocate(Heap hp, int size)
{
    // 试图从last所指向的struct mblock对象中分配内存
    Block *blk = hp->last;

    // 确保子区间[avail,end)足够大
    while (size > blk->end - blk->avail) {
        if ((blk->next = FreeBlocks) != NULL) {
            // 首先尝试从空闲块链FreeBlocks中找出一块足够大的内存
            FreeBlocks = FreeBlocks->next;
            blk = blk->next;
        } else {
            // 通过malloc()分配一块新的内存空间
            int m = size + BLOCK_SIZE + sizeof(Block);

            blk->next = (Block*) malloc(m);
            blk = blk->next;
            if (blk == NULL) {
                LOGE("Memory exhausted");
                exit(EXT_MemoryFull);
            }
            blk->end = (char*) blk + m;
        }

        blk->avail = blk->begin = (char*) (blk + 1);
        blk->next = NULL;
        hp->last = blk;
    }
    blk->avail += size;

    return blk->avail - size;
}

// 释放堆的所有内存块，回收到空闲块列表中
void FreeHeap(Heap hp)
{
    hp->last->next = FreeBlocks;
    FreeBlocks = hp->head.next;
    InitHeap(hp);
}

static void FreeBlock(Block *blk)
{
    while (blk != NULL) {
        Block *p = blk;
        blk = blk->next;
        free(p);
    }
}

// 清理释放堆内存
void DestroyHeap(Heap hp)
{
    FreeBlock(hp->head.next);
    InitHeap(hp);
    if (FreeBlocks != NULL) {
        FreeBlock(FreeBlocks);
        FreeBlocks = NULL;
    }
}
